home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
RTF
/
textflow.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
5KB
|
294 lines
/* $Header: /usr/people/pcd/Src/RTF/RCS/textflow.C,v 1.1 92/11/23 12:58:56 pcd Exp Locker: pcd $
*/
#include "textflow.h"
#include <string.h>
#include <assert.h>
int debug_node = 0;
#include "debug.h"
Node::Node(Node* par)
{
parent_ = par;
left_ = right_ = 0;
left_child_ = right_child_ = 0;
}
Node::Node(Node* par, Node* lef, Node* rt)
{
Debug(node, ("Node::Node lef = %lx rt = %lx\n", lef, rt));
parent_ = par;
left_ = right_ = 0;
left_child_ = right_child_ = 0;
connect(lef, rt);
}
void
Node::connect(Node* lef, Node* rt)
{
Debug(node, ("connect parent=%lx left=%lx this = %lx rt=%lx\n",
parent(), lef, this, rt));
assert(lef == 0 || lef != rt);
left_ = lef;
if(lef){
Debug(node, ("this left: %x\n", lef));
right_ = lef->right();
lef->right_ = this;
}else{
Debug(node, ("this is left child\n"));
right_ = parent()->left_child();
parent_->left_child_ = this;
}
if(right()){
Debug(node, ("this right: %x\n", right()));
right_->left_ = this;
}else
parent_->right_child_ = this;
if(rt)
consume(rt);
}
void
Node::consume(Node* rt)
{
Debug(node, ("this->right_child: %x\n", rt));
left_child_ = right_;
right_child_ = rt;
assert(left_child_->parent_ == right_child_->parent_);
right_ = rt->right_;
if(right())
right_->left_ = this;
else
parent_->right_child_ = this;
left_child_->left_ = 0;
right_child_->right_ = 0;
Node* ch;
for(ch = left_child_; ch != right_child_; ch = ch->right_)
ch->parent_ = this;
right_child_->parent_ = this;
}
Node::~Node()
{
// ASSUME left_child_ == 0 ==> right_child_ == 0
Node* d = left_child_;
while(1){
delete d;
if(d == right_child_)
break;
else
d = d->right();
}
}
void
Node::disconnect()
{
if(left() == 0 && right() == 0)
if(parent_ != this) // else root node
parent_->disconnect();
else{
if(left())
left_->right_ = right();
else
parent_->left_child_ = right();
if(right())
right_->left_ = left();
else
parent_->right_child_ = right();
}
delete this;
}
TextFlow::TextFlow(const Byte* d, Qty q)
: Node(this)
{
assert(q>0);
bytes_ = q;
data_ = new Byte[q];
memcpy(data_, d, q); //@# int!
new TextFlow(*this, 0, data_, q);
}
TextFlow::~TextFlow()
{
if(parent() == this)
delete data_;
}
TextFlow::TextFlow(TextFlow& par, TextFlow* left, const Byte* d, Qty q)
: Node(&par, left, 0)
{
data_ = (Byte*)d;
bytes_ = q;
}
TextFlow::TextFlow(TextFlow& p, TextPosition first, TextPosition last)
: Node(&p, p.start_branch(first)->left(), 0)
{
bytes_ = 0; // during end_branch
consume(p.end_branch(last));
data_ = (Byte*)p.data() + first;
bytes_ = last - first;
}
Qty
TextFlow::bytes_before() const
{
Qty b = 0;
TextFlow* s = left();
while(s){
b += s->bytes();
s = s->left();
}
return b;
}
Qty
TextFlow::bytes_after() const
{
Qty b = 0;
TextFlow* s = right();
while(s){
b += s->bytes();
s = s->right();
}
return b;
}
TextFlow*
TextFlow::start_branch(Qty offset)
{
assert(offset < bytes());
if(!left_child()){ // leaf
if(offset == 0)
return this;
else{ // split
Qty n = bytes() - offset;
bytes_ = offset;
return new TextFlow(*parent(), this, data() + bytes(), n);
}
}
TextFlow* b;
for(b = left_child(); offset >= b->bytes(); b = b->right())
offset -= b->bytes();
TextFlow* bb = b->start_branch(offset);
if(this == bb->parent())
return bb;
else
return b;
}
TextFlow*
TextFlow::end_branch(Qty offset)
{
assert(offset>0);
if(!left_child()){ // leaf
if(offset == bytes())
return this;
else{ // split
Qty q = bytes() - offset;
bytes_ = offset;
new TextFlow(*parent(), this, data()+bytes(), q);
return this;
}
}
TextFlow* b;
for(b = left_child(); offset > b->bytes(); b = b->right())
offset -= b->bytes();
TextFlow* bb = b->end_branch(offset);
if(this == bb->parent())
return bb;
else
return b;
}
const TextFlow*
TextFlow::subflow(TextPosition first, TextPosition last) const
{
if(left_child() == 0)
return this;
TextFlow* ret;
for(ret = left_child(); first >= ret->bytes(); ret = ret->right())
first -= ret->bytes(), last -= ret->bytes();
if(last > ret->bytes())
return this;
return ret;
}
const TextFlow*
TextFlow::leaf(TextPosition first, TextPosition& move) const
{
if(left_child() == 0)
return this;
TextFlow* ret;
for(ret = left_child(); first >= ret->bytes(); ret = ret->right())
move -= ret->bytes(), first -= ret->bytes();
return ret->leaf(first, move);
}
void
TextFlow::line_shape(TextPosition pos, Extent& shape) const
{
if(parent() != this){
parent()->line_shape(pos+bytes_before(), shape);
return;
}
Extent empty(0,0,0,0,0);
shape = empty;
}
Qty
TextFlow::character_shape(TextPosition first, Qty qq,
Extent avail, Extent& used, int wrap) const
{
if(parent() != this)
return parent()->character_shape(first+bytes_before(),
qq,
avail, used, wrap);
used.x2 = -1; /* don't change justification */
used.x0 = used.y0 = used.y1 = 0;
return qq;
}
void
TextFlow::render(TextPosition first, Qty last, Point o) const
{
if(parent() != this){
parent()->render(first+bytes_before(), last+bytes_before(), o);
return;
}
return;
};